/******************************************************************************
 * Copyright (C) 2012 ShenZhen ComTop Information Technology Co.,Ltd
 * All Rights Reserved.
 * 本软件为深圳康拓普开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、
 * 复制、修改或发布本软件.
 *****************************************************************************/

package com.code.common.nio;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;

import org.apache.log4j.Logger;

/**
 * 传输服务器接收类
 *
 * @author 陈大周
 * @since 1.0
 * @version 2012-12-10 陈大周
 */
public class ReceivingServer implements Runnable {

    /**  日志对象 */
    private final static Logger logger = Logger.getLogger(ReceivingServer.class);

    Selector selector = null;

    ServerSocketChannel serverSocketChannel = null;

    private ExecutorService  executorService = TransferManager.getExecutorService();

    /**
     * 执行选择器查询
     *
     * @param serverSocketChannel
     * @throws IOException
     */
    @SuppressWarnings("unchecked")
    private void execute(ServerSocketChannel serverSocketChannel) throws IOException {
        SocketChannel socketChannel = null;
        try {
            socketChannel = serverSocketChannel.accept();
            byte[] bytes = receiveData(socketChannel);
         	//executorService.execute( new SavingTask(bytes) );
        } finally {
            try {
                socketChannel.close();
            } catch (Exception ex) {
            }
        }
    }


    /**
     * 接收客戶端的数据
     *
     * @param socketChannel
     * @return
     * @throws IOException
     */
    private static byte[] receiveData(SocketChannel socketChannel) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        byte[] bytes=null;
        try {
            int size = 0;
            while ((size = socketChannel.read(buffer)) >= 0) {
                buffer.flip();
                bytes = new byte[size];
                buffer.get(bytes);
                baos.write(bytes);
                buffer.clear();
            }
            bytes = baos.toByteArray();
        } finally {
            try {
                baos.close();
            } catch (Exception ex) {
            }
        }
        return bytes;
    }


    /**
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        int iTransferPort = 9999;
        while (true) {
            try {
                // 打开一个选择器
                selector = Selector.open();
                // 打开一个选择器通道
                serverSocketChannel = ServerSocketChannel.open();
                serverSocketChannel.configureBlocking(false);

                // 绑定本地IP和端口
                serverSocketChannel.socket().setReuseAddress(true);

                serverSocketChannel.socket().bind(new InetSocketAddress(iTransferPort));

                // 注册选择器
                serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

                // 遍历选择器
                while (selector.select() > 0) {
                    Iterator<SelectionKey> it = selector.selectedKeys().iterator();
                    // 遍历选择器
                    while (it.hasNext()) {
                        SelectionKey readyKey = it.next();
                        it.remove();
                        // 查询选择器
                        execute((ServerSocketChannel) readyKey.channel());
                    }
                }
            } catch (ClosedChannelException ex) {
                logger.error("选择器已关闭异常", ex);
            } catch (IOException ex) {
                logger.error("NIO读写异常", ex);
            } finally {
                try {
                    selector.close();
                } catch (Exception ex) {
                }
                try {
                    serverSocketChannel.close();
                } catch (Exception ex) {
                }
            }
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                logger.error("连接失败,3秒重连", e);
            }
        }
    }
}